home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / macos / uae069b2.src.cpt.hqx / UAE069ß2.SRC.CPT / uae069fl2.src / fpp.c < prev    next >
C/C++ Source or Header  |  1997-06-28  |  28KB  |  1,141 lines

  1.  /*
  2.   * UAE - The Un*x Amiga Emulator
  3.   *
  4.   * MC68881 emulation
  5.   *
  6.   * Copyright 1996 Herman ten Brugge
  7.   */
  8.  
  9. // ATB
  10. #pragma optimization_level 2
  11. ///
  12.  
  13. #include <math.h>
  14.  
  15. #include "sysconfig.h"
  16. #include "sysdeps.h"
  17.  
  18. #include "config.h"
  19. #include "options.h"
  20. #include "my_memory.h"
  21. #include "custom.h"
  22. #include "readcpu.h"
  23. #include "newcpu.h"
  24. #include "ersatz.h"
  25.  
  26. #if CPU_LEVEL >= 3
  27.  
  28. #define    DEBUG_FPP    0
  29.  
  30. /* single   : S  8*E 23*F */
  31. /* double   : S 11*E 52*F */
  32. /* extended : S 15*E 64*F */
  33. /* E = 0 & F = 0 -> 0 */
  34. /* E = MAX & F = 0 -> Infin */
  35. /* E = MAX & F # 0 -> NotANumber */
  36. /* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */
  37.  
  38. static __inline__ double
  39. to_single(uae_u32 value)
  40. {
  41.     double frac;
  42.  
  43.     if ((value & 0x7fffffff) == 0) return(0.0);
  44.     frac = (double)((value & 0x7fffff) | 0x800000) / 8388608.0;
  45.     if (value & 0x80000000) frac = -frac;
  46.     return(ldexp(frac, ((value >> 23) & 0xff) - 127));
  47. }
  48.  
  49. static __inline__ uae_u32
  50. from_single(double src)
  51. {
  52.     int expon;
  53.     uae_u32 tmp;
  54.     double frac;
  55.  
  56.     if (src == 0.0) return 0;
  57.     if (src < 0) { tmp = 0x80000000 ; src = -src; }
  58.     else { tmp = 0; }
  59.     frac = frexp(src,&expon);
  60.     frac += 0.5 / 16777216.0;
  61.     if (frac >= 1.0) { frac /= 2.0; expon++; }
  62.     return (tmp | (((expon + 127 - 1) & 0xff) << 23) |
  63.         (((int)(frac * 16777216.0)) & 0x7fffff));
  64. }
  65.  
  66. static __inline__ double
  67. to_exten(uae_u32 wrd1,uae_u32 wrd2,uae_u32 wrd3)
  68. {
  69.     double frac;
  70.  
  71.     if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) return 0.0;
  72.     frac = (double)wrd2 / 2147483648.0 +
  73.            (double)wrd3 / 9223372036854775808.0;
  74.     if (wrd1 & 0x80000000) frac = -frac;
  75.     return ldexp(frac, ((wrd1 >> 16) & 0x7fff) - 16383);
  76. }
  77.  
  78. static __inline__ void
  79. from_exten(double src,uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 * wrd3)
  80. {
  81.     int expon;
  82.     double frac;
  83.  
  84.     if (src == 0.0) { *wrd1 = 0; *wrd2 = 0; *wrd3 = 0; return; }
  85.     if (src < 0) { *wrd1 = 0x80000000 ; src = -src; }
  86.     else { *wrd1 = 0; }
  87.     frac = frexp(src,&expon);
  88.     frac += 0.5 / 18446744073709551616.0;
  89.     if (frac >= 1.0) { frac /= 2.0; expon++; }
  90.     *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16);
  91.     *wrd2 = (uae_u32)(frac * 4294967296.0);
  92.     *wrd3 = (uae_u32)(frac * 18446744073709551616.0 - *wrd2 * 4294967296.0);
  93. }
  94.  
  95. static __inline__ double
  96. to_double(uae_u32 wrd1,uae_u32 wrd2)
  97. {
  98.     double frac;
  99.  
  100.     if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) return 0.0;
  101.     frac = (double)((wrd1 & 0xfffff) | 0x100000) / 1048576.0 +
  102.            (double)wrd2 / 4503599627370496.0;
  103.     if (wrd1 & 0x80000000) frac = -frac;
  104.     return ldexp(frac, ((wrd1 >> 20) & 0x7ff) - 1023);
  105. }
  106.  
  107. static __inline__ void
  108. from_double(double src,uae_u32 *wrd1, uae_u32 *wrd2)
  109. {
  110.     int expon;
  111.     int tmp;
  112.     double frac;
  113.  
  114.     if (src == 0.0) { *wrd1 = 0; *wrd2 = 0; return; }
  115.     if (src < 0) { *wrd1 = 0x80000000 ; src = -src; }
  116.     else { *wrd1 = 0; }
  117.     frac = frexp(src,&expon);
  118.     frac += 0.5 / 9007199254740992.0;
  119.     if (frac >= 1.0) { frac /= 2.0; expon++; }
  120.     tmp = (uae_u32)(frac * 2097152.0);
  121.     *wrd1 |= (((expon + 1023 - 1) & 0x7ff) << 20) | (tmp & 0xfffff);
  122.     *wrd2 = (uae_u32)(frac * 9007199254740992.0 - tmp * 4294967296.0);
  123. }
  124.  
  125. static __inline__ double
  126. to_pack(uae_u32 wrd1,uae_u32 wrd2,uae_u32 wrd3)
  127. {
  128.     double d;
  129.     char *cp;
  130.     char str[100];
  131.  
  132.     cp = str;
  133.     if (wrd1 & 0x80000000) *cp++ = '-';
  134.     *cp++ = (wrd1 & 0xf) + '0';
  135.     *cp++ = '.';
  136.     *cp++ = ((wrd2 >> 28) & 0xf) + '0';
  137.     *cp++ = ((wrd2 >> 24) & 0xf) + '0';
  138.     *cp++ = ((wrd2 >> 20) & 0xf) + '0';
  139.     *cp++ = ((wrd2 >> 16) & 0xf) + '0';
  140.     *cp++ = ((wrd2 >> 12) & 0xf) + '0';
  141.     *cp++ = ((wrd2 >> 8) & 0xf) + '0';
  142.     *cp++ = ((wrd2 >> 4) & 0xf) + '0';
  143.     *cp++ = ((wrd2 >> 0) & 0xf) + '0';
  144.     *cp++ = ((wrd3 >> 28) & 0xf) + '0';
  145.     *cp++ = ((wrd3 >> 24) & 0xf) + '0';
  146.     *cp++ = ((wrd3 >> 20) & 0xf) + '0';
  147.     *cp++ = ((wrd3 >> 16) & 0xf) + '0';
  148.     *cp++ = ((wrd3 >> 12) & 0xf) + '0';
  149.     *cp++ = ((wrd3 >> 8) & 0xf) + '0';
  150.     *cp++ = ((wrd3 >> 4) & 0xf) + '0';
  151.     *cp++ = ((wrd3 >> 0) & 0xf) + '0';
  152.     *cp++ = 'E';
  153.     if (wrd1 & 0x40000000) *cp++ = '-';
  154.     *cp++ = ((wrd1 >> 24) & 0xf) + '0';
  155.     *cp++ = ((wrd1 >> 20) & 0xf) + '0';
  156.     *cp++ = ((wrd1 >> 16) & 0xf) + '0';
  157.     *cp = 0;
  158.     sscanf(str,"%le",&d);
  159.     return d;
  160. }
  161.  
  162. static __inline__ void
  163. from_pack(double src,uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 * wrd3)
  164. {
  165.     int i;
  166.     int t;
  167.     char *cp;
  168.     char str[100];
  169.  
  170.     sprintf(str,"%.16e",src);
  171.     cp = str;
  172.     *wrd1 = *wrd2 = *wrd3 = 0;
  173.     if (*cp == '-') { cp++ ; *wrd1 = 0x80000000; }
  174.     if (*cp == '+') cp++;
  175.     *wrd1 |= (*cp++ - '0');
  176.     if (*cp == '.') cp++;
  177.     for (i = 0 ; i < 8 ; i++) {
  178.         *wrd2 <<= 4;
  179.         if (*cp >= '0' && *cp <= '9')
  180.             *wrd2 |= *cp++ - '0';
  181.     }
  182.     for (i = 0 ; i < 8 ; i++) {
  183.         *wrd3 <<= 4;
  184.         if (*cp >= '0' && *cp <= '9')
  185.             *wrd3 |= *cp++ - '0';
  186.     }
  187.     if (*cp == 'e' || *cp == 'E') {
  188.         cp++;
  189.         if (*cp == '-') { cp++; *wrd1 |= 0x40000000; }
  190.         if (*cp == '+') cp++;
  191.         t = 0;
  192.         for (i = 0 ; i < 3 ; i++) {
  193.             if (*cp >= '0' && *cp <= '9')
  194.                 t = (t << 4) | (*cp++ - '0');
  195.         }
  196.         *wrd1 |= t << 16;
  197.     }
  198. }
  199.  
  200. static __inline__ int
  201. get_fp_value(uae_u32 opcode, uae_u16 extra,double *src)
  202. {
  203.     int size;
  204.     int mode;
  205.     int reg;
  206.     uae_u32 ad = 0;
  207.     static int sz1[8] = { 4,4,12,12,2,8,1,0 };
  208.     static int sz2[8] = { 4,4,12,12,2,8,2,0 };
  209.  
  210.     if ((extra & 0x4000) == 0) {
  211.         *src = regs.fp[(extra >> 10) & 7];
  212.         return 1;
  213.     }
  214.     mode = (opcode >> 3) & 7;
  215.     reg = opcode & 7;
  216.     size = (extra >> 10) & 7;
  217.     switch (mode) {
  218.     case 0:
  219.         switch (size) {
  220.         case 6: *src = (double)(uae_s8)m68k_dreg(regs, reg);
  221.             break;
  222.         case 4: *src = (double)(uae_s16)m68k_dreg(regs, reg);
  223.             break;
  224.         case 0: *src = (double)(uae_s32)m68k_dreg(regs, reg);
  225.             break;
  226.         case 1: *src = to_single(m68k_dreg(regs, reg));
  227.             break;
  228.         default:
  229.             return 0;
  230.         }
  231.         return 1;
  232.     case 1:
  233.         return 0;
  234.     case 2:
  235.         ad = m68k_areg(regs, reg);
  236.         break;
  237.     case 3:
  238.         ad = m68k_areg(regs, reg);
  239.         m68k_areg(regs, reg) += reg == 7 ? sz2[size] : sz1[size];
  240.         break;
  241.     case 4:
  242.         m68k_areg(regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
  243.         ad = m68k_areg(regs, reg);
  244.         break;
  245.     case 5:
  246.         ad = m68k_areg(regs, reg) + (uae_s32)(uae_s16)nextiword();
  247.         break;
  248.     case 6:
  249.         ad = get_disp_ea(m68k_areg(regs, reg));
  250.         break;
  251.     case 7:
  252.         switch (reg) {
  253.         case 0: ad = (uae_s32)(uae_s16)nextiword();
  254.             break;
  255.         case 1: ad = nextilong();
  256.             break;
  257.         case 2: ad = m68k_getpc();
  258.             ad += (uae_s32)(uae_s16)nextiword();
  259.             break;
  260.         case 3: ad = get_disp_ea(m68k_getpc());
  261.             break;
  262.         case 4: ad = m68k_getpc();
  263.             m68k_setpc(ad + sz2[size]);
  264.             break;
  265.         default:
  266.             return 0;
  267.         }
  268.     }
  269.     switch (size) {
  270.     case 0: *src = (double)(uae_s32)get_long(ad);
  271.         break;
  272.     case 1: *src = to_single(get_long(ad));
  273.         break;
  274.     case 2:    { uae_u32 wrd1,wrd2,wrd3;
  275.           wrd1 = get_long(ad);ad+=4;
  276.           wrd2 = get_long(ad);ad+=4;
  277.           wrd3 = get_long(ad);
  278.           *src = to_exten(wrd1,wrd2,wrd3);
  279.         }
  280.         break;
  281.     case 3:    { uae_u32 wrd1,wrd2,wrd3;
  282.           wrd1 = get_long(ad);ad+=4;
  283.           wrd2 = get_long(ad);ad+=4;
  284.           wrd3 = get_long(ad);
  285.           *src = to_pack(wrd1,wrd2,wrd3);
  286.         }
  287.         break;
  288.     case 4: *src = (double)(uae_s16)get_word(ad);
  289.         break;
  290.     case 5:    { uae_u32 wrd1,wrd2;
  291.           wrd1 = get_long(ad);ad+=4;
  292.           wrd2 = get_long(ad);
  293.           *src = to_double(wrd1,wrd2);
  294.         }
  295.         break;
  296.     case 6: *src = (double)(uae_s8)get_byte(ad);
  297.         break;
  298.     default:
  299.         return 0;
  300.     }
  301.     return 1;
  302. }
  303.  
  304. static __inline__ int
  305. put_fp_value(double value, uae_u32 opcode, uae_u16 extra)
  306. {
  307.     int size;
  308.     int mode;
  309.     int reg;
  310.     uae_u32 ad;
  311.     static int sz1[8] = { 4,4,12,12,2,8,1,0 };
  312.     static int sz2[8] = { 4,4,12,12,2,8,2,0 };
  313.  
  314.     if ((extra & 0x4000) == 0) {
  315.         regs.fp[(extra >> 10) & 7] = value;
  316.         return 1;
  317.     }
  318.     mode = (opcode >> 3) & 7;
  319.     reg = opcode & 7;
  320.     size = (extra >> 10) & 7;
  321.     ad = -1;
  322.     switch (mode) {
  323.     case 0:
  324.         switch (size) {
  325.         case 6: m68k_dreg(regs, reg) = ((int)value & 0xff) |
  326.                       (m68k_dreg(regs, reg) & ~0xff);
  327.             break;
  328.         case 4: m68k_dreg(regs, reg) = ((int)value & 0xffff) |
  329.                       (m68k_dreg(regs, reg) & ~0xffff);
  330.             break;
  331.         case 0: m68k_dreg(regs, reg) = (int)value;
  332.             break;
  333.         case 1: m68k_dreg(regs, reg) = from_single(value);
  334.             break;
  335.         default:
  336.             return 0;
  337.         }
  338.         return 1;
  339.     case 1:
  340.         return 0;
  341.     case 2:
  342.         ad = m68k_areg(regs, reg);
  343.         break;
  344.     case 3:
  345.         ad = m68k_areg(regs, reg);
  346.         m68k_areg(regs, reg) += reg == 7 ? sz2[size] : sz1[size];
  347.         break;
  348.     case 4:
  349.         m68k_areg(regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
  350.         ad = m68k_areg(regs, reg);
  351.         break;
  352.     case 5:
  353.         ad = m68k_areg(regs, reg) + (uae_s32)(uae_s16)nextiword();
  354.         break;
  355.     case 6:
  356.         ad = get_disp_ea(m68k_areg(regs, reg));
  357.         break;
  358.     case 7:
  359.         switch (reg) {
  360.         case 0: ad = (uae_s32)(uae_s16)nextiword();
  361.             break;
  362.         case 1: ad = nextilong();
  363.             break;
  364.         case 2: ad = m68k_getpc();
  365.             ad += (uae_s32)(uae_s16)nextiword();
  366.             break;
  367.         case 3: ad = get_disp_ea(m68k_getpc());
  368.             break;
  369.         case 4: ad = m68k_getpc();
  370.             m68k_setpc(ad + sz2[size]);
  371.             break;
  372.         default:
  373.             return 0;
  374.         }
  375.     }
  376.     switch (size) {
  377.     case 0: put_long(ad,(uae_s32)value);
  378.         break;
  379.     case 1: put_long(ad,from_single(value));
  380.         break;
  381.     case 2:    { uae_u32 wrd1,wrd2,wrd3;
  382.           from_exten(value,&wrd1,&wrd2,&wrd3);
  383.           put_long(ad,wrd1);ad+=4;
  384.           put_long(ad,wrd2);ad+=4;
  385.           put_long(ad,wrd3);
  386.         }
  387.         break;
  388.     case 3:    { uae_u32 wrd1,wrd2,wrd3;
  389.           from_pack(value,&wrd1,&wrd2,&wrd3);
  390.           put_long(ad,wrd1);ad+=4;
  391.           put_long(ad,wrd2);ad+=4;
  392.           put_long(ad,wrd3);
  393.         }
  394.         break;
  395.     case 4: put_word(ad,(uae_s16)value);
  396.         break;
  397.     case 5:    { uae_u32 wrd1,wrd2;
  398.           from_double(value,&wrd1,&wrd2);
  399.           put_long(ad,wrd1);ad+=4;
  400.           put_long(ad,wrd2);
  401.         }
  402.         break;
  403.     case 6: put_byte(ad,(uae_s8)value);
  404.         break;
  405.     default:
  406.         return 0;
  407.     }
  408.     return 1;
  409. }
  410.  
  411. static __inline__ int
  412. get_fp_ad(uae_u32 opcode,uae_u32 *ad)
  413. {
  414.     int mode;
  415.     int reg;
  416.  
  417.     mode = (opcode >> 3) & 7;
  418.     reg = opcode & 7;
  419.     switch (mode) {
  420.     case 0:
  421.     case 1:
  422.         return 0;
  423.     case 2:
  424.         *ad = m68k_areg(regs, reg);
  425.         break;
  426.     case 3:
  427.         *ad = m68k_areg(regs, reg);
  428.         break;
  429.     case 4:
  430.         *ad = m68k_areg(regs, reg);
  431.         break;
  432.     case 5:
  433.         *ad = m68k_areg(regs, reg) + (uae_s32)(uae_s16)nextiword();
  434.         break;
  435.     case 6:
  436.         *ad = get_disp_ea(m68k_areg(regs, reg));
  437.         break;
  438.     case 7:
  439.         switch (reg) {
  440.         case 0: *ad = (uae_s32)(uae_s16)nextiword();
  441.             break;
  442.         case 1: *ad = nextilong();
  443.             break;
  444.         case 2: *ad = m68k_getpc();
  445.             *ad += (uae_s32)(uae_s16)nextiword();
  446.             break;
  447.         case 3: *ad = get_disp_ea(m68k_getpc());
  448.             break;
  449.         default:
  450.             return 0;
  451.         }
  452.     }
  453.     return 1;
  454. }
  455.  
  456. static __inline__ int
  457. fpp_cond(uae_u32 opcode, int contition)
  458. {
  459.     int N = (regs.fpsr & 0x8000000) != 0;
  460.     int Z = (regs.fpsr & 0x4000000) != 0;
  461.     /* int I = (regs.fpsr & 0x2000000) != 0; */
  462.     int NotANumber = (regs.fpsr & 0x1000000) != 0;
  463.  
  464.     switch (contition) {
  465.     case 0x00: return 0;
  466.     case 0x01: return Z;
  467.     case 0x02: return !(NotANumber || Z || N);
  468.     case 0x03: return Z || !(NotANumber || N);
  469.     case 0x04: return N && !(NotANumber || Z);
  470.     case 0x05: return Z || (N && !NotANumber);
  471.     case 0x06: return !(NotANumber || Z);
  472.     case 0x07: return !NotANumber;
  473.     case 0x08: return NotANumber;
  474.     case 0x09: return NotANumber || Z;
  475.     case 0x0a: return NotANumber || !(N || Z);
  476.     case 0x0b: return NotANumber || Z || !N;
  477.     case 0x0c: return NotANumber || (N && !Z);
  478.     case 0x0d: return NotANumber || Z || N;
  479.     case 0x0e: return !Z;
  480.     case 0x0f: return 1;
  481.     case 0x10: return 0;
  482.     case 0x11: return Z;
  483.     case 0x12: return !(NotANumber || Z || N);
  484.     case 0x13: return Z || !(NotANumber || N);
  485.     case 0x14: return N && !(NotANumber || Z);
  486.     case 0x15: return Z || (N && !NotANumber);
  487.     case 0x16: return !(NotANumber || Z);
  488.     case 0x17: return !NotANumber;
  489.     case 0x18: return NotANumber;
  490.     case 0x19: return NotANumber || Z;
  491.     case 0x1a: return NotANumber || !(N || Z);
  492.     case 0x1b: return NotANumber || Z || !N;
  493.     case 0x1c: return NotANumber || (Z && N);
  494.     case 0x1d: return NotANumber || Z || N;
  495.     case 0x1e: return !Z;
  496.     case 0x1f: return 1;
  497.     }
  498.     return -1;
  499. }
  500.  
  501. void
  502. fdbcc_opp(uae_u32 opcode, uae_u16 extra)
  503. {
  504.     uaecptr pc = (uae_u32)m68k_getpc();
  505.     uae_s32 disp = (uae_s32)(uae_s16)nextiword();
  506.     int cc;
  507.  
  508. #if DEBUG_FPP
  509.     printf("fdbcc_opp at %08lx\n",m68k_getpc());fflush(stdout);
  510. #endif
  511.     cc = fpp_cond(opcode, extra & 0x3f);
  512.     if (cc == -1) {
  513.         m68k_setpc(pc-2);
  514.         op_illg(opcode);
  515.     } else if (!cc) {
  516.         int reg = opcode & 0x7;
  517.         
  518.         m68k_dreg(regs, reg) = ((m68k_dreg(regs, reg) & ~0xffff) 
  519.                     | ((m68k_dreg(regs, reg)-1) & 0xffff));
  520.         if ((m68k_dreg(regs, reg) & 0xffff) == 0xffff)
  521.         m68k_setpc(pc + disp);
  522.     }
  523. }
  524.  
  525. void
  526. fscc_opp(uae_u32 opcode, uae_u16 extra)
  527. {
  528.     uae_u32 ad;
  529.     int cc;
  530.  
  531. #if DEBUG_FPP
  532.     printf("fscc_opp at %08lx\n",m68k_getpc());fflush(stdout);
  533. #endif
  534.     cc = fpp_cond(opcode, extra & 0x3f);
  535.     if (cc == -1) {
  536.         m68k_setpc(m68k_getpc()-2);
  537.         op_illg(opcode);
  538.     }
  539.     else if ((opcode & 0x38) == 0) {
  540.         m68k_dreg(regs, opcode & 7) = (m68k_dreg(regs, opcode & 7) & ~0xff) |
  541.                         (cc ? 0xff : 0x00);
  542.     }
  543.     else {
  544.         if (get_fp_ad(opcode,&ad) == 0) {
  545.             m68k_setpc(m68k_getpc()-2);
  546.             op_illg(opcode);
  547.         }
  548.         else
  549.             put_byte(ad,cc ? 0xff : 0x00);
  550.     }
  551. }
  552.  
  553. void
  554. ftrapcc_opp(uae_u32 opcode, uaecptr oldpc)
  555. {
  556.     int cc;
  557.  
  558. #if DEBUG_FPP
  559.     printf("ftrapcc_opp at %08lx\n",m68k_getpc());fflush(stdout);
  560. #endif
  561.     cc = fpp_cond(opcode, opcode & 0x3f);
  562.     if (cc == -1) {
  563.         m68k_setpc(oldpc);
  564.         op_illg(opcode);
  565.     }
  566.     if (cc)
  567.         Exception(7,oldpc-2);
  568. }
  569.  
  570. void
  571. fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra)
  572. {
  573.     int cc;
  574.  
  575. #if DEBUG_FPP
  576.     printf("fbcc_opp at %08lx\n",m68k_getpc());fflush(stdout);
  577. #endif
  578.     cc = fpp_cond(opcode, opcode & 0x3f);
  579.     if (cc == -1) {
  580.         m68k_setpc(pc);
  581.         op_illg(opcode);
  582.     }
  583.     else if (cc) {
  584.         if ((opcode & 0x40) == 0)
  585.             extra = (uae_s32)(uae_s16)extra;
  586.         m68k_setpc(pc + extra);
  587.     }
  588. }
  589.  
  590. void
  591. fsave_opp(uae_u32 opcode)
  592. {
  593.     uae_u32 ad;
  594.     int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
  595.     int i;
  596.     
  597. #if DEBUG_FPP
  598.     printf("fsave_opp at %08lx\n",m68k_getpc());fflush(stdout);
  599. #endif
  600.     if (get_fp_ad(opcode,&ad) == 0) {
  601.         op_illg(opcode);
  602.         return;
  603.     }
  604.     if (incr < 0) {
  605.         ad -= 4;put_long(ad,0x70000000);
  606.         for (i = 0 ; i < 5 ; i++) {
  607.             ad -= 4;put_long(ad,0x00000000);
  608.         }
  609.         ad -= 4;put_long(ad,0x1f180000);
  610.     }
  611.     else {
  612.         put_long(ad,0x1f180000); ad += 4;
  613.         for (i = 0 ; i < 5 ; i++) {
  614.             put_long(ad,0x00000000); ad += 4;
  615.         }
  616.         put_long(ad,0x70000000); ad += 4;
  617.     }
  618.     if ((opcode & 0x38) == 0x18) m68k_areg(regs, opcode & 7) = ad;
  619.     if ((opcode & 0x38) == 0x20) m68k_areg(regs, opcode & 7) = ad;
  620. }
  621.  
  622. void
  623. frestore_opp(uae_u32 opcode)
  624. {
  625.     uae_u32 ad;
  626.     uae_u32 d;
  627.     int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
  628.     
  629. #if DEBUG_FPP
  630.     printf("frestore_opp at %08lx\n",m68k_getpc());fflush(stdout);
  631. #endif
  632.     if (get_fp_ad(opcode,&ad) == 0) {
  633.         op_illg(opcode);
  634.         return;
  635.     }
  636.     if (incr < 0) {
  637.         ad -= 4; d = get_long(ad);
  638.         if ((d & 0xff000000) != 0) {
  639.             if ((d & 0x00ff0000) == 0x00180000)
  640.                 ad -= 6 * 4;
  641.             else if ((d & 0x00ff0000) == 0x00380000)
  642.                 ad -= 14 * 4;
  643.             else if ((d & 0x00ff0000) == 0x00b40000)
  644.                 ad -= 45 * 4;
  645.         }
  646.     }
  647.     else {
  648.         d = get_long(ad); ad += 4;
  649.         if ((d & 0xff000000) != 0) {
  650.             if ((d & 0x00ff0000) == 0x00180000)
  651.                 ad += 6 * 4;
  652.             else if ((d & 0x00ff0000) == 0x00380000)
  653.                 ad += 14 * 4;
  654.             else if ((d & 0x00ff0000) == 0x00b40000)
  655.                 ad += 45 * 4;
  656.         }
  657.     }
  658.     if ((opcode & 0x38) == 0x18) m68k_areg(regs, opcode & 7) = ad;
  659.     if ((opcode & 0x38) == 0x20) m68k_areg(regs, opcode & 7) = ad;
  660. }
  661.  
  662. void
  663. fpp_opp(uae_u32 opcode, uae_u16 extra)
  664. {
  665.     int reg;
  666.     double src;
  667.  
  668. #if DEBUG_FPP
  669.     printf("FPP %04lx %04x at %08lx\n",opcode & 0xffff,extra & 0xffff,
  670.                        m68k_getpc()-4);fflush(stdout);
  671. #endif
  672.     switch ((extra >> 13) & 0x7) {
  673.     case 3:
  674.         if (put_fp_value(regs.fp[(extra >> 7) & 7], opcode, extra)== 0){
  675.             m68k_setpc(m68k_getpc()-2);
  676.             op_illg(opcode);
  677.         }
  678.         return;
  679.     case 4:
  680.     case 5:
  681.         if ((opcode & 0x38) == 0) {
  682.             if (extra & 0x2000) {
  683.                 if (extra & 0x1000)
  684.                     m68k_dreg(regs, opcode & 7) = regs.fpcr;
  685.                 if (extra & 0x0800)
  686.                     m68k_dreg(regs, opcode & 7) = regs.fpsr;
  687.                 if (extra & 0x0400)
  688.                     m68k_dreg(regs, opcode & 7) = regs.fpiar;
  689.             }
  690.             else {
  691.                 if (extra & 0x1000)
  692.                     regs.fpcr = m68k_dreg(regs, opcode & 7);
  693.                 if (extra & 0x0800)
  694.                     regs.fpsr = m68k_dreg(regs, opcode & 7);
  695.                 if (extra & 0x0400)
  696.                     regs.fpiar = m68k_dreg(regs, opcode & 7);
  697.             }
  698.         }
  699.         else if ((opcode & 0x38) == 1) {
  700.             if (extra & 0x2000) {
  701.                 if (extra & 0x1000)
  702.                     m68k_areg(regs, opcode & 7) = regs.fpcr;
  703.                 if (extra & 0x0800)
  704.                     m68k_areg(regs, opcode & 7) = regs.fpsr;
  705.                 if (extra & 0x0400)
  706.                     m68k_areg(regs, opcode & 7) = regs.fpiar;
  707.             }
  708.             else {
  709.                 if (extra & 0x1000)
  710.                     regs.fpcr = m68k_areg(regs, opcode & 7);
  711.                 if (extra & 0x0800)
  712.                     regs.fpsr = m68k_areg(regs, opcode & 7);
  713.                 if (extra & 0x0400)
  714.                     regs.fpiar = m68k_areg(regs, opcode & 7);
  715.             }
  716.         }
  717.         else if ((opcode & 0x3f) == 0x3c) {
  718.             if ((extra & 0x2000) == 0) {
  719.                 if (extra & 0x1000)
  720.                     regs.fpcr = nextilong();
  721.                 if (extra & 0x0800)
  722.                     regs.fpsr = nextilong();
  723.                 if (extra & 0x0400)
  724.                     regs.fpiar = nextilong();
  725.             }
  726.         }
  727.         else if (extra & 0x2000) {
  728.             /* FMOVEM FPP->memory */
  729.             uae_u32 ad;
  730.             int incr = 0;
  731.  
  732.             if (get_fp_ad(opcode,&ad) == 0) {
  733.                 m68k_setpc(m68k_getpc()-2);
  734.                 op_illg(opcode);
  735.                 return;
  736.             }
  737.             if ((opcode & 0x38) == 0x20) { 
  738.                 if (extra & 0x1000) incr += 4;
  739.                 if (extra & 0x0800) incr += 4;
  740.                 if (extra & 0x0400) incr += 4;
  741.             }
  742.             ad -= incr;
  743.             if (extra & 0x1000) {
  744.                 put_long(ad,regs.fpcr);ad+=4;
  745.             }
  746.             if (extra & 0x0800) {
  747.                 put_long(ad,regs.fpsr);ad+=4;
  748.             }
  749.             if (extra & 0x0400) {
  750.                 put_long(ad,regs.fpiar);ad+=4;
  751.             }
  752.             ad -= incr;
  753.             if ((opcode & 0x38) == 0x18) m68k_areg(regs, opcode & 7) = ad;
  754.             if ((opcode & 0x38) == 0x20) m68k_areg(regs, opcode & 7) = ad;
  755.         }
  756.         else {
  757.             /* FMOVEM memory->FPP */
  758.             uae_u32 ad;
  759.  
  760.             if (get_fp_ad(opcode,&ad) == 0) {
  761.                 m68k_setpc(m68k_getpc()-2);
  762.                 op_illg(opcode);
  763.                 return;
  764.             }
  765.             ad = (opcode & 0x38) == 0x20 ? ad-12 : ad;
  766.             if (extra & 0x1000) {
  767.                 regs.fpcr = get_long(ad);ad+=4;
  768.             }
  769.             if (extra & 0x0800) {
  770.                 regs.fpsr = get_long(ad);ad+=4;
  771.             }
  772.             if (extra & 0x0400) {
  773.                 regs.fpiar = get_long(ad);ad+=4;
  774.             }
  775.             if ((opcode & 0x38) == 0x18) m68k_areg(regs, opcode & 7) = ad;
  776.             if ((opcode & 0x38) == 0x20) m68k_areg(regs, opcode & 7) = ad-12;
  777.         }
  778.         return;
  779.     case 6:
  780.     case 7:
  781.         {
  782.             uae_u32 ad,list = 0;
  783.             int incr = 0;
  784.             if (extra & 0x2000) {
  785.             /* FMOVEM FPP->memory */
  786.             if (get_fp_ad(opcode,&ad) == 0) {
  787.                 m68k_setpc(m68k_getpc()-2);
  788.                 op_illg(opcode);
  789.                 return;
  790.             }
  791.             switch ((extra >> 11) & 3) {
  792.             case 0:    /* static pred */
  793.                 list = extra & 0xff;
  794.                 incr = -1;
  795.                 break;
  796.             case 1: /* dynamic pred */
  797.                 list = m68k_dreg(regs, (extra >> 4) & 3) & 0xff;
  798.                 incr = -1;
  799.                 break;
  800.             case 2: /* static postinc */
  801.                 list = extra & 0xff;
  802.                 incr = 1;
  803.                 break;
  804.             case 3: /* dynamic postinc */
  805.                 list = m68k_dreg(regs, (extra >> 4) & 3) & 0xff;
  806.                 incr = 1;
  807.                 break;
  808.             }
  809.             while (list) {
  810.                 uae_u32 wrd1,wrd2,wrd3;
  811.                 if (incr < 0) {
  812.                     from_exten(
  813.                         regs.fp[fpp_movem_index2[list]],
  814.                         &wrd1,&wrd2,&wrd3);
  815.                     ad-=4;put_long(ad,wrd3);
  816.                     ad-=4;put_long(ad,wrd2);
  817.                     ad-=4;put_long(ad,wrd1);
  818.                 }
  819.                 else {
  820.                     from_exten(
  821.                         regs.fp[fpp_movem_index1[list]],
  822.                         &wrd1,&wrd2,&wrd3);
  823.                     put_long(ad,wrd1);ad+=4;
  824.                     put_long(ad,wrd2);ad+=4;
  825.                     put_long(ad,wrd3);ad+=4;
  826.                 }
  827.                 list = fpp_movem_next[list];
  828.             }
  829.             if ((opcode & 0x38) == 0x18) m68k_areg(regs, opcode & 7) = ad;
  830.             if ((opcode & 0x38) == 0x20) m68k_areg(regs, opcode & 7) = ad;
  831.             }
  832.             else {
  833.             /* FMOVEM memory->FPP */
  834.             if (get_fp_ad(opcode,&ad) == 0) {
  835.                 m68k_setpc(m68k_getpc()-2);
  836.                 op_illg(opcode);
  837.                 return;
  838.             }
  839.             switch ((extra >> 11) & 3) {
  840.             case 0:    /* static pred */
  841.                 list = extra & 0xff;
  842.                 incr = -1;
  843.                 break;
  844.             case 1: /* dynamic pred */
  845.                 list = m68k_dreg(regs, (extra >> 4) & 3) & 0xff;
  846.                 incr = -1;
  847.                 break;
  848.             case 2: /* static postinc */
  849.                 list = extra & 0xff;
  850.                 incr = 1;
  851.                 break;
  852.             case 3: /* dynamic postinc */
  853.                 list = m68k_dreg(regs, (extra >> 4) & 3) & 0xff;
  854.                 incr = 1;
  855.                 break;
  856.             }
  857.             while (list) {
  858.                 uae_u32 wrd1,wrd2,wrd3;
  859.                 if (incr < 0) {
  860.                     ad-=4;wrd3 = get_long(ad);
  861.                     ad-=4;wrd2 = get_long(ad);
  862.                     ad-=4;wrd1 = get_long(ad);
  863.                     regs.fp[fpp_movem_index2[list]] =
  864.                         to_exten(wrd1,wrd2,wrd3);
  865.                 }
  866.                 else {
  867.                     wrd1 = get_long(ad);ad+=4;
  868.                     wrd2 = get_long(ad);ad+=4;
  869.                     wrd3 = get_long(ad);ad+=4;
  870.                     regs.fp[fpp_movem_index1[list]] =
  871.                         to_exten(wrd1,wrd2,wrd3);
  872.                 }
  873.                 list = fpp_movem_next[list];
  874.             }
  875.             if ((opcode & 0x38) == 0x18) m68k_areg(regs, opcode & 7) = ad;
  876.             if ((opcode & 0x38) == 0x20) m68k_areg(regs, opcode & 7) = ad;
  877.             }
  878.         }
  879.         return;
  880.     case 0:
  881.     case 2:
  882.         reg = (extra >> 7) & 7;
  883.         if ((extra & 0xfc00) == 0x5c00) {
  884.             switch (extra & 0x7f) {
  885.             case 0x00: regs.fp[reg] = 4.0*atan(1.0); break;
  886.             case 0x0b: regs.fp[reg] = log10(2.0); break;
  887.             case 0x0c: regs.fp[reg] = exp(1.0); break;
  888.             case 0x0d: regs.fp[reg] = log(exp(1.0))/log(2.0); break;
  889.             case 0x0e: regs.fp[reg] = log(exp(1.0))/log(10.0); break;
  890.             case 0x0f: regs.fp[reg] = 0.0; break;
  891.             case 0x30: regs.fp[reg] = log(2.0); break;
  892.             case 0x31: regs.fp[reg] = log(10.0); break;
  893.             case 0x32: regs.fp[reg] = 1.0e0; break;
  894.             case 0x33: regs.fp[reg] = 1.0e1; break;
  895.             case 0x34: regs.fp[reg] = 1.0e2; break;
  896.             case 0x35: regs.fp[reg] = 1.0e4; break;
  897.             case 0x36: regs.fp[reg] = 1.0e8; break;
  898.             case 0x37: regs.fp[reg] = 1.0e16; break;
  899.             case 0x38: regs.fp[reg] = 1.0e32; break;
  900.             case 0x39: regs.fp[reg] = 1.0e64; break;
  901.             case 0x3a: regs.fp[reg] = 1.0e128; break;
  902.             case 0x3b: regs.fp[reg] = 1.0e256; break;
  903. #if 0
  904.             case 0x3c: regs.fp[reg] = 1.0e512; break;
  905.             case 0x3d: regs.fp[reg] = 1.0e1024; break;
  906.             case 0x3e: regs.fp[reg] = 1.0e2048; break;
  907.             case 0x3f: regs.fp[reg] = 1.0e4096; break;
  908. #endif
  909.             default:
  910.                 m68k_setpc(m68k_getpc()-2);
  911.                 op_illg(opcode);
  912.                 break;
  913.             }
  914.             return;
  915.         }
  916.         if (get_fp_value(opcode, extra, &src) == 0) {
  917.             m68k_setpc(m68k_getpc()-2);
  918.             op_illg(opcode);
  919.             return;
  920.         }
  921.         switch (extra & 0x7f) {
  922.         case 0x00:    /* FMOVE */
  923.             regs.fp[reg] = src;
  924.             break;
  925.         case 0x01:    /* FINT */
  926.             regs.fp[reg] = (int)(src + 0.5);
  927.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  928.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  929.             break;
  930.         case 0x02:    /* FSINH */
  931.             regs.fp[reg] = sinh(src);
  932.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  933.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  934.             break;
  935.         case 0x03:    /* FINTRZ */
  936.             regs.fp[reg] = (int)src;
  937.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  938.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  939.             break;
  940.         case 0x04:    /* FSQRT */
  941.             regs.fp[reg] = sqrt(src);
  942.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  943.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  944.             break;
  945.         case 0x06:    /* FLOGNP1 */
  946.             regs.fp[reg] = log(src + 1.0);
  947.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  948.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  949.             break;
  950.         case 0x08:    /* FETOXM1 */
  951.             regs.fp[reg] = exp(src) - 1.0;
  952.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  953.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  954.             break;
  955.         case 0x09:    /* FTANH */
  956.             regs.fp[reg] = tanh(src);
  957.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  958.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  959.             break;
  960.         case 0x0a:    /* FATAN */
  961.             regs.fp[reg] = atan(src);
  962.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  963.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  964.             break;
  965.         case 0x0c:    /* FASIN */
  966.             regs.fp[reg] = asin(src);
  967.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  968.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  969.             break;
  970.         case 0x0d:    /* FATANH */
  971. #if 1 /* The BeBox doesn't have atanh, and it isn't in the HPUX libm either */
  972.             regs.fp[reg] = log((1+src)/(1-src))/2;
  973. #else
  974.             regs.fp[reg] = atanh(src);
  975. #endif
  976.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  977.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  978.             break;
  979.         case 0x0e:    /* FSIN */
  980.             regs.fp[reg] = sin(src);
  981.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  982.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  983.             break;
  984.         case 0x0f:    /* FTAN */
  985.             regs.fp[reg] = tan(src);
  986.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  987.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  988.             break;
  989.         case 0x10:    /* FETOX */
  990.             regs.fp[reg] = exp(src);
  991.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  992.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  993.             break;
  994.         case 0x11:    /* FTWOTOX */
  995.             regs.fp[reg] = pow(2.0,src);
  996.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  997.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  998.             break;
  999.         case 0x12:    /* FTENTOX */
  1000.             regs.fp[reg] = pow(10.0,src);
  1001.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1002.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1003.             break;
  1004.         case 0x14:    /* FLOGN */
  1005.             regs.fp[reg] = log(src);
  1006.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1007.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1008.             break;
  1009.         case 0x15:    /* FLOG10 */
  1010.             regs.fp[reg] = log10(src);
  1011.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1012.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1013.             break;
  1014.         case 0x16:    /* FLOG2 */
  1015.             regs.fp[reg] = log(src) / log(2.0);
  1016.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1017.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1018.             break;
  1019.         case 0x18:    /* FABS */
  1020.             regs.fp[reg] = src < 0 ? -src : src;
  1021.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1022.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1023.             break;
  1024.         case 0x19:    /* FCOSH */
  1025.             regs.fp[reg] = cosh(src);
  1026.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1027.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1028.             break;
  1029.         case 0x1a:    /* FNEG */
  1030.             regs.fp[reg] = -src;
  1031.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1032.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1033.             break;
  1034.         case 0x1c:    /* FACOS */
  1035.             regs.fp[reg] = acos(src);
  1036.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1037.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1038.             break;
  1039.         case 0x1d:    /* FCOS */
  1040.             regs.fp[reg] = cos(src);
  1041.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1042.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1043.             break;
  1044.         case 0x1e:    /* FGETEXP */
  1045.             { int expon;
  1046.             frexp(src,&expon);
  1047.             regs.fp[reg] = (double)(expon-1);
  1048.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1049.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1050.             }
  1051.             break;
  1052.         case 0x1f:    /* FGETMAN */
  1053.             { int expon;
  1054.             regs.fp[reg] = frexp(src,&expon) * 2.0;
  1055.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1056.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1057.             }
  1058.             break;
  1059.         case 0x20:    /* FDIV */
  1060.             regs.fp[reg] /= src;
  1061.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1062.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1063.             break;
  1064.         case 0x21:    /* FMOD */
  1065.             regs.fp[reg] = regs.fp[reg] - 
  1066.                 (double)((int)(regs.fp[reg] / src)) * src;
  1067.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1068.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1069.             break;
  1070.         case 0x22:    /* FADD */
  1071.             regs.fp[reg] += src;
  1072.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1073.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1074.             break;
  1075.         case 0x23:    /* FMUL */
  1076.             regs.fp[reg] *= src;
  1077.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1078.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1079.             break;
  1080.         case 0x24:    /* FSGLDIV */
  1081.             regs.fp[reg] /= src;
  1082.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1083.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1084.             break;
  1085.         case 0x25:    /* FREM */
  1086.             regs.fp[reg] = regs.fp[reg] - 
  1087.                 (double)((int)(regs.fp[reg] / src + 0.5)) * src;
  1088.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1089.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1090.             break;
  1091.         case 0x26:    /* FSCALE */
  1092.             regs.fp[reg] *= exp(log(2.0)*src);
  1093.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1094.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1095.             break;
  1096.         case 0x27:    /* FSGLMUL */
  1097.             regs.fp[reg] *= src;
  1098.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1099.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1100.             break;
  1101.         case 0x28:    /* FSUB */
  1102.             regs.fp[reg] -= src;
  1103.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1104.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1105.             break;
  1106.         case 0x30:    /* FSINCOS */
  1107.         case 0x31:
  1108.         case 0x32:
  1109.         case 0x33:
  1110.         case 0x34:
  1111.         case 0x35:
  1112.         case 0x36:
  1113.         case 0x37:
  1114.             regs.fp[reg] = sin(src);
  1115.             regs.fp[extra & 7] = cos(src);
  1116.             regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
  1117.                     (regs.fp[reg] < 0 ? 0x8000000 : 0);
  1118.             break;
  1119.         case 0x38:    /* FCMP */
  1120.             { double tmp = regs.fp[reg] - src;
  1121.             regs.fpsr = (tmp == 0 ? 0x4000000 : 0) |
  1122.                     (tmp < 0 ? 0x8000000 : 0);
  1123.             }
  1124.             break;
  1125.         case 0x3a:    /* FTST */
  1126.             regs.fpsr = (src == 0 ? 0x4000000 : 0) |
  1127.                     (src < 0 ? 0x8000000 : 0);
  1128.             break;
  1129.         default:
  1130.             m68k_setpc(m68k_getpc()-2);
  1131.             op_illg(opcode);
  1132.             break;
  1133.         }
  1134.         return;
  1135.     }
  1136.     m68k_setpc(m68k_getpc()-2);
  1137.     op_illg(opcode);
  1138. }
  1139.  
  1140. #endif
  1141.